#ifndef FILESYSTEMMANAGER_H
#define FILESYSTEMMANAGER_H

#include "Device.h"
#include "DeviceDriver.h"

extern int device_list[1];
int current_directory;
extern int currently_mounted;

/**
 * Marks a device port as occupied. Allowing the OS to mount or format it in the future.
 * @author Daniel Fairweather
 * @param port The device port number (Between 1 and 4).
 * @returns 0 on success,
 *          -1 if the port number is out of range, 
 *          -2 if the port has already been initialized.
 */
int init_device(int port);



/**
 * Compares two strings.
 * @author Ying Wang
 * @param string1 The pointer to the first string.
 * @param string2 The pointer to the second string.
 * @returns int 0 if the two strings are identical,
 *              -1 if not.
 */
int string_cmp(char* string1, char* string2);



/**
 * Copies one string's content to another.
 * @author Ying Wang
 * @param string1 The pointer to the string to be copied.
 * @param string2 The pointer to the string to be copy to.
 * @returns void.
 */
void string_copy(char* string1, char* string2);



/**
 * Formats a device and establishes a filesystem with the specified name and blocksize.
 * @author Daniel Fairweather
 * @param port The device port number (Must be 0).
 * @param fs_name The name of the filesystem.
 * @param blocksize The size (in KB) for blocks in the new FS.
 * @returns 0 on success,
 *          -1 if the port number is out of range, 
 *          -2 if the port hasn't been initialized,
 *          -3 if the blocksize is out of range.
 */
int format_fs(int port, char* fs_name, int blocksize);



/**
 * Creates a file on the filesystem.
 * @author Daniel Fairweather
 * @param filename The name of the file to be created.
 * @param isDirectory Whether or not the file we are creating is a directory.
 * @returns block number on success,
 *          -1 if there are no remaining free blocks.
 *          -99 if no filesystem has been mounted.
 */
int create_file(char* filename, int isDirectory);



/**
 * Mount the specified file system.
 * @author Ying Wang
 * @param fs_name The name of the file system.
 * @returns 0 on success,
 *          -1 if there's a file system mounted already,
 *          -2 if no such file system exists.
 */
int mount_fs(char* fs_name);



/**
 * Unmount the specified file system.
 * @author Ying Wang
 * @param fs_name The name of the file system.
 * @returns 0 on success,
 *          -1 if there's no file system mounted already,
 *          -2 if the file system was not currently mounted.
 */
int unmount_fs(char* fs_name);



/**
 * Determines whether or not a file exists in the current directory.
 * @author Daniel Fairweather
 * @param filename The name of the file to check for.
 * @returns -1 if no such file exists in the current directory.
 *          The block number of the FCB on success.
 */
int file_exists(char* filename);



/**
 * Determines whether or not a directory exists in the current directory.
 * @author Daniel Fairweather
 * @param directoryname The name of the directory to check for.
 * @returns -1 if no such directory exists in the current directory.
 *          The block number of the FCB on success.
 */
int directory_exists(char* directoryname);



/**
 * Determines whether or not a file exists in the current directory.
 * @author Daniel Fairweather
 * @param filename The name of the file to check for.
 * @returns -1 if no such file exists in the current directory.
 *          The block number of the FCB on success.
 */
int file_exists(char* filename);



/**
 * Gets an available filehandle.
 * @author Ying Wang
 * @returns >=0 on success,
 *          -1 if there's no available filehandle.
 */
int get_free_filehandle();



/**
 * Opens the specified file with the given mode.
 * @author Ying Wang
 * @param filename The name of the file to be opened.
 * @param filename The mode of the file to be opened in.
 * @returns >=0 the filehandle on success,
 *          -1 if the specified file doesn't exist,
 *          -2 if there's no available filehandle.
 *          -99 if no filesystem has been mounted.
 */
int open_file(char* filename, int mode);



/**
 * Reads the content from the specified file.
 * @author Ying Wang
 * @param filehandle The handle of the file to be read.
 * @param blocknumber The blocknumber to be read.
 * @param buffer The buffer to put the content in.
 * @returns 0 on success,
 *          -1 if the block is not in the specified file,
 *          -2 if the file is not opened in read mode,
 *			-3 if the buffer is invalid,
 *			-4 if the file handle is invalid.
 *          -99 if no filesystem has been mounted.
 */
int read_file(int filehandle, int blocknumber, int buffer);



/**
 * Writes the content to the specified file.
 * @author Ying Wang
 * @param filehandle The handle of the file to be written to.
 * @param blocknumber The blocknumber to be written to.
 * @param buffer The buffer of the actual content.
 * @returns 0 on success,
 *          1 on success and file extension,
 *          -1 if the block is taken by other files,
 *          -2 if the file is not opened in write mode,
 *			-3 if the buffer is invalid,
 *			-4 if the file handle is invalid,
 *          -5 if add_address command failed,
 *			-6 if the block number is invalid.
 *          -99 if no filesystem has been mounted.
 */
int write_file(int filehandle, int blocknumber, int buffer);



/**
 * Closes the handle of the specified file.
 * @author Ying Wang
 * @param filehandle The handle of the file to be closed.
 * @returns 0 on success,
 *          -1 if the file is not opened.
 *          -99 if no filesystem has been mounted.
 */
int close_file(int filehandle);



/**
 * Closes the handle of the all open files.
 * @author Ying Wang
 * @returns 0 on success.
 */
void close_open_files();



/**
 * Delete the specified file.
 * @author Ying Wang
 * @param filename The name of the file to be deleted.
 * @returns 0 on success,
 *          -1 if the filehandle is not valid,
 *          -99 if no filesystem has been mounted.
 */
int delete_file(char* filename);



/**
 * Recursively deletes a directory.
 * @author Daniel Fairweather
 * @param directory The name of the directory to be deleted.
 * @returns 0 on success,
 *          -1 if the filehandle is not valid,
 *          -99 if no filesystem has been mounted.
 */
int delete_directory(char* directory_name);



/**
 * Change the current directory.
 * @author Ying Wang
 * @param directory The name of the directory to be entered.
 * @returns 0 on success,
 *          -1 if the directory is not valid,
 *          -99 if no filesystem has been mounted.
 */
int cd_directory(char* directory);

#endif